package com.cee.quartz.job.base;

import com.cee.enums.StatusEnum;
import com.cee.quartz.job.JobType;
import com.cee.sch.job.dto.ScheduleJobDTO;
import com.cee.sch.job.dto.ScheduleJobLogDTO;
import com.cee.sch.job.enumeration.JobExecutionStatus;
import com.cee.sch.job.service.ScheduleJobLogService;
import com.cee.sch.job.service.ScheduleJobService;
import com.cee.util.ExceptionUtil;
import com.cee.util.SystemUtil;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;

public abstract class BaseQuartzJob implements Job {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    protected ScheduleJobService scheduleJobService;

    @Autowired
    protected ScheduleJobLogService scheduleJobLogService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        logger.info("Start to execute the job {}", jobDetail.getKey());

        ScheduleJobDTO schduleJobDTO = null;
        try {
            schduleJobDTO = scheduleJobService.getScheduleJobByNameAndGroup(jobDetail.getKey().getName(), jobDetail.getKey().getGroup());
            if (schduleJobDTO == null) {
                throw new IllegalStateException("could not find the schedule job with key: " + jobDetail.getKey().getName() + "-" + jobDetail.getKey().getGroup());
            }
        } catch (SchedulerException e) {
            throw new IllegalStateException(e);
        }

        String enabledInd = schduleJobDTO.getEnabledInd();
        logger.info("{}-{} enabledInd: {}", jobDetail.getKey().getName(), jobDetail.getKey().getGroup(), enabledInd);

        if (SystemUtil.getBooleanConfigValue(SystemUtil.SYS_BATCH_JOB_SWITCH_IND) && StatusEnum.Yes.getCode().equals(enabledInd)) {
            // set context user

            // create job log
            ScheduleJobLogDTO jobLog = new ScheduleJobLogDTO();
            try {
                jobLog.setStartTime(new Date());
                jobLog.setStatus(JobExecutionStatus.PROGRESS.getCode());
                jobLog = scheduleJobLogService.addScheduleJobLog(jobDetail.getKey().getName(), jobDetail.getKey().getGroup(), jobLog);

                // execute job
                executeJob(jobDetail, jobLog);

            } catch (Exception e) {
                logger.error("{}", ExceptionUtil.getFullStackTrace(e));
                jobLog.setStatus(JobExecutionStatus.FAILED.getCode());
                jobLog.setErrorMsg(e.getMessage());
                jobLog.setEndTime(new Date());
                jobLog.setRecFail(1L);
                jobLog.setRecTotal(1L);
                scheduleJobLogService.updateScheduleJobLog(jobLog);
            }

            // update as complete status
            if (JobType.LOCAL.equals(getJobType()) && JobExecutionStatus.PROGRESS.getCode().equals(jobLog.getStatus())) {
                // update job log
                jobLog.setEndTime(new Date());
                jobLog.setStatus(JobExecutionStatus.COMPLETE.getCode());
                scheduleJobLogService.updateScheduleJobLog(jobLog);
            }
        } else {
            logger.info("SYS_BATCH_JOB_SWITCH_IND is Off, so skip the job.");
        }

        logger.info("Execute the job {} end", jobDetail.getKey());
    }

    protected abstract void executeJob(JobDetail jobDetail, ScheduleJobLogDTO jobLog) throws Exception;

    protected abstract JobType getJobType();
}
